#pragma once
#include <iostream>
#include <cassert>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctime>
#include <cstdlib>
#include "Task.h"

using namespace std;

#define PROCESS_NUM 5

int waitCommand(int waitfd, bool& quit)//如果对方不发送信息，我们就阻塞
{
    uint32_t command = 0;
    ssize_t s = read(waitfd,&command,sizeof(command));
    if(s == 0)//读到文件结尾，退出
    {
        quit = true;
        return -1;
    }
    assert(s == sizeof(uint32_t));
    return command; 
}
void sendAndWakeup(pid_t who, int fd, uint32_t command)
{
    write(fd,&command,sizeof(command));
    cout<< "main process: call process " << who << " execute " << demp[command] << " through " << fd << endl;
}
int main()
{
    //将处理方法插入
    load();

    //第一个时子进程id，第二个是fd
    vector<pair<pid_t, int>>slots;

    //先创建多个进程
    for(int i = 0; i < PROCESS_NUM; i++)
    {
        int pipefd[2] = {0};
        //创建管道
        int n = pipe(pipefd);
        //成功返回零，否则返回-1
        assert(n == 0);

        //创建子进程
        pid_t id = fork();

        assert(id != -1);
        if(id == 0)
        {
            //子进程
            //子进程关闭写入端口
            close(pipefd[1]);
            while(true)
            {
                //等命令
                bool quit = false;
                int command = waitCommand(pipefd[0],quit);
                //执行对应的命令
                if(quit)
                {
                    break;
                }
                if(command >= 0 && command < HandlerSize())
                {
                    callbacks[command]();
                }
                else
                {
                    cout << "非法输入命令" << endl;
                }
            }
            exit(1);
        }

        //父进程
        //父进程关闭读入端口
        close(pipefd[0]);
        //插入子进程id和写入端口的fd
        slots.push_back(make_pair(id,pipefd[1]));
    }

    //父进程派发任务
    srand((unsigned long)time(nullptr));
    int count = 0;
    while(count < 10)
    {
        //1.自动派发任务写法
        count++;
        //选择一个任务
        int command = rand() % HandlerSize();
        //选择一个进程
        int choice = rand() % slots.size();
        //把任务派发给指定进程
        sendAndWakeup(slots[choice].first, slots[choice].second, command);
        sleep(1);
        //2.手动进行派发任务
        // int select;
        // int command;

        // cout << "################################################" << endl;
        // cout << "####   1.show functions    2.send command   ####" << endl;
        // cout << "################################################" << endl;
        // cout << "please select> " ;
        // cin >> select;
        // if(select == 1) showHandler();
        // else if(select == 2)
        // {
        //     cout << "Entet you command> ";
        //     //选择任务
        //     cin >>command;
        //     //选择进程
        //     int choice = rand() % slots.size();
        //     //把任务派发给指定进程
        //     sendAndWakeup(slots[choice].first, slots[choice].second, command);
        // }
    } 

    //关闭fd，结束所有进程
    for(const auto& solt : slots)
    {
        close(solt.second);
    }
    // 回收所有的子进程信息
    for (const auto &slot : slots)
    {
        waitpid(slot.first, nullptr, 0);
    }
    return 0;
}